{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "541b1de9-2f3b-4461-a72e-e13d63a06746",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import mindspore as ms\n",
    "import mindspore.nn as nn\n",
    "import mindspore.dataset as ds\n",
    "import mindspore.dataset.transforms.c_transforms as C\n",
    "from mindspore import dtype as mstype\n",
    "from mindspore.common.initializer import Normal\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import StandardScaler\n",
    "import joblib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "21c0f7c5-06f1-41d7-96f9-cfbfea132a88",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# 读取数据集文件\n",
    "dataset =  pd.read_csv('./data/processed_data/dataset6classes.csv')\n",
    "dataset.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "2a5d023e-f5ca-46b8-a101-4236a66078d1",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 2, 4, 1, 3])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset = dataset.drop('Unnamed: 0', 1)\n",
    "dataset[\" Label\"].unique()      # 查看Label的类别"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e36da384-da3b-42c6-b5f8-af20ecca936b",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "feature_lenth = dataset.shape[1]\n",
    "data = dataset.iloc[:,:feature_lenth-1] # 获取特征属性列\n",
    "label = dataset[' Label']               # 获取Label属性列，\n",
    "\n",
    "# 分割数据集为训练集、验证集和测试集\n",
    "X_train, X_test, y_train, y_test = train_test_split(data, label,test_size=0.1, random_state=1)\n",
    "X_train, X_val, y_train, y_val = train_test_split(X_train, y_train,test_size=0.2, random_state=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6b84277a-77df-4a34-929b-5c06585b8e6f",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['./StandardScaler2.save']"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将训练集的均值和方差作为总样本的参数分布\n",
    "standard_scaler = StandardScaler()\n",
    "standard_scaler.fit(X_train)\n",
    "\n",
    "# 对数据集进行标准化处理\n",
    "X_train = standard_scaler.transform(X_train)\n",
    "X_val = standard_scaler.transform(X_val)\n",
    "X_test = standard_scaler.transform(X_test)\n",
    "\n",
    "# 保存缩放器模型\n",
    "scaler_save_path = \"./model_saved/StandardScaler.save\"\n",
    "joblib.dump(standard_scaler, scaler_save_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "37aba3a6-fa72-42fd-86b7-9efb15be094f",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "train examples: 473152\n",
      "validation examples 118288\n",
      "test examples: 65716\n"
     ]
    }
   ],
   "source": [
    "print('train examples:', len(X_train))\n",
    "print( 'validation examples', len(X_val))\n",
    "print('test examples:', len(X_test) )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "caddd578-6ae4-435f-813c-4d612ef632e4",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "\n",
    "# 自定义数据源\n",
    "class MyAccessible:\n",
    "    def __init__(self, X, y):\n",
    "        self._data = np.array(X)\n",
    "        self._label = np.array(y)\n",
    "\n",
    "    def __getitem__(self, index):\n",
    "        return self._data[index], self._label[index]\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self._data)\n",
    "\n",
    "# 创建数据集，使之符合模型输入的要求\n",
    "def Ceate_dataset(X, y, shuffle_size = 200, batch_size=128):\n",
    "    ds.config.set_seed(123)     # 设置随机种子，保证每次随机化处理的结果相同\n",
    "    dataset = ds.GeneratorDataset(source=MyAccessible(X, y), column_names=[\"data\", \"label\"])\n",
    "    dataset = dataset.map(operations=C.TypeCast(mstype.float32), input_columns=[\"data\"])    # 特征属性列的数据类型统一为float32\n",
    "    dataset = dataset.map(operations=C.TypeCast(mstype.int32), input_columns=[\"label\"])     # 类别属性的数据类型设为int32\n",
    "    dataset = dataset.shuffle(shuffle_size)\n",
    "    dataset = dataset.batch(batch_size)\n",
    "    return dataset\n",
    "\n",
    "# 得到训练集、验证集和测试集\n",
    "data_train = Ceate_dataset(X_train, y_train)\n",
    "data_val = Ceate_dataset(X_val, y_val)\n",
    "data_test = Ceate_dataset(X_test, y_test)\n",
    "\n",
    "# # 查看数据集中的前五条数据，观察数据类型和大小\n",
    "# iterator = data_test.create_dict_iterator()\n",
    "# i =0\n",
    "# for item in iterator:\n",
    "#     # item is a dict\n",
    "#     i +=1\n",
    "#     print(item)\n",
    "#     if i==10:\n",
    "#         break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "1e957d86-83d7-49af-ab35-c32b79c28e0a",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "\n",
    "class DNN(nn.Cell):\n",
    "    \"\"\"定义深度神经网络结构\"\"\"\n",
    "    def __init__(self, input_dims=11, output_dims=5, dropout_ratio=0.2):\n",
    "        super(DNN, self).__init__()\n",
    "        self.input_dims = input_dims\n",
    "        self.output_dims = output_dims\n",
    "        self.dropout_ratio = dropout_ratio\n",
    "        # 定义所需要的运算\n",
    "        self.fc1 = nn.Dense(self.input_dims, 512, weight_init=Normal(0.02))\n",
    "        self.fc2 = nn.Dense(512, 256, weight_init=Normal(0.02))\n",
    "        self.fc3 = nn.Dense(256, 128, weight_init=Normal(0.02))\n",
    "        self.fc4 = nn.Dense(128, 64, weight_init=Normal(0.02))\n",
    "        self.fc5 = nn.Dense(64, self.output_dims, weight_init=Normal(0.02))\n",
    "        self.relu = nn.ReLU()\n",
    "        self.log_softmax = nn.LogSoftmax()\n",
    "        self.dropout = nn.Dropout(keep_prob=dropout_ratio)\n",
    "\n",
    "    # 使用定义好的运算构建前向网络\n",
    "    def construct(self, x):\n",
    "\n",
    "        x = self.fc1(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.dropout(x)\n",
    "\n",
    "        x = self.fc2(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.dropout(x)\n",
    "\n",
    "        x = self.fc3(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.dropout(x)\n",
    "\n",
    "        x = self.fc4(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.dropout(x)\n",
    "\n",
    "        x = self.fc5(x)\n",
    "        x = self.log_softmax(x)\n",
    "        return x\n",
    "# 网络实例化\n",
    "net = DNN()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6b10ed8c-5b3a-4dca-8cf1-8905e55a359e",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "from mindspore import Model\n",
    "from mindspore.nn import SoftmaxCrossEntropyWithLogits\n",
    "from mindspore.nn import SGD, Adam\n",
    "from mindspore.nn.metrics import Accuracy\n",
    "\n",
    "lr = 0.0001   # 学习率\n",
    "#定义损失函数\n",
    "loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n",
    "#定义优化器（待更新的参数，学习率，权重衰减）\n",
    "optim = Adam(params=net.trainable_params(), learning_rate=lr, weight_decay=0.01)\n",
    "#实例化模型对象（网络结构，损失函数，优化器，评价指标）\n",
    "model = Model(network=net,loss_fn=loss,optimizer=optim,metrics={'accuracy': Accuracy()})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "617bff1f-36f6-4860-b9b4-7b288adb5e0e",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---------------开始训练-------------\n",
      "epoch: 1 step: 1000, loss is 0.9638172388076782\n",
      "epoch: 1 step: 2000, loss is 0.8211514353752136\n",
      "epoch: 1 step: 3000, loss is 0.5580129623413086\n",
      "epoch: 2 step: 303, loss is 0.37132251262664795\n",
      "epoch: 2 step: 1303, loss is 0.3668070137500763\n",
      "epoch: 2 step: 2303, loss is 0.3831019103527069\n",
      "epoch: 2 step: 3303, loss is 0.34128567576408386\n",
      "验证集准确率为: {'accuracy': 0.9162298796158528}\n",
      "epoch: 3 step: 606, loss is 0.404092937707901\n",
      "epoch: 3 step: 1606, loss is 0.5582598447799683\n",
      "epoch: 3 step: 2606, loss is 0.35104385018348694\n",
      "epoch: 3 step: 3606, loss is 0.38596564531326294\n",
      "epoch: 4 step: 909, loss is 0.294807493686676\n",
      "epoch: 4 step: 1909, loss is 0.4008302390575409\n",
      "epoch: 4 step: 2909, loss is 0.27310097217559814\n",
      "验证集准确率为: {'accuracy': 0.9305762207493575}\n",
      "epoch: 5 step: 212, loss is 0.3179163634777069\n",
      "epoch: 5 step: 1212, loss is 0.2543521523475647\n",
      "epoch: 5 step: 2212, loss is 0.29405146837234497\n",
      "epoch: 5 step: 3212, loss is 0.26114270091056824\n",
      "epoch: 6 step: 515, loss is 0.249850794672966\n",
      "epoch: 6 step: 1515, loss is 0.1967962235212326\n",
      "epoch: 6 step: 2515, loss is 0.3437327742576599\n",
      "epoch: 6 step: 3515, loss is 0.21695563197135925\n",
      "验证集准确率为: {'accuracy': 0.931480792641688}\n",
      "epoch: 7 step: 818, loss is 0.2360164076089859\n",
      "epoch: 7 step: 1818, loss is 0.26525306701660156\n",
      "epoch: 7 step: 2818, loss is 0.47287988662719727\n",
      "epoch: 8 step: 121, loss is 0.3011430501937866\n",
      "epoch: 8 step: 1121, loss is 0.2848264276981354\n",
      "epoch: 8 step: 2121, loss is 0.21570047736167908\n",
      "epoch: 8 step: 3121, loss is 0.25052201747894287\n",
      "验证集准确率为: {'accuracy': 0.9301873393750846}\n",
      "epoch: 9 step: 424, loss is 0.3193442225456238\n",
      "epoch: 9 step: 1424, loss is 0.2135888934135437\n",
      "epoch: 9 step: 2424, loss is 0.24232132732868195\n",
      "epoch: 9 step: 3424, loss is 0.3493567109107971\n",
      "epoch: 10 step: 727, loss is 0.2526402175426483\n",
      "epoch: 10 step: 1727, loss is 0.3711300790309906\n",
      "epoch: 10 step: 2727, loss is 0.24978187680244446\n",
      "验证集准确率为: {'accuracy': 0.9301788854321655}\n",
      "epoch: 11 step: 30, loss is 0.3838188350200653\n",
      "epoch: 11 step: 1030, loss is 0.3312799036502838\n",
      "epoch: 11 step: 2030, loss is 0.35113874077796936\n",
      "epoch: 11 step: 3030, loss is 0.28902480006217957\n",
      "epoch: 12 step: 333, loss is 0.3289121687412262\n",
      "epoch: 12 step: 1333, loss is 0.27037400007247925\n",
      "epoch: 12 step: 2333, loss is 0.36806437373161316\n",
      "epoch: 12 step: 3333, loss is 0.24908971786499023\n",
      "验证集准确率为: {'accuracy': 0.930787569322332}\n",
      "epoch: 13 step: 636, loss is 0.31657737493515015\n",
      "epoch: 13 step: 1636, loss is 0.3002266585826874\n",
      "epoch: 13 step: 2636, loss is 0.29410573840141296\n",
      "epoch: 13 step: 3636, loss is 0.2902418076992035\n",
      "epoch: 14 step: 939, loss is 0.34310269355773926\n",
      "epoch: 14 step: 1939, loss is 0.2950718104839325\n",
      "epoch: 14 step: 2939, loss is 0.21274831891059875\n",
      "验证集准确率为: {'accuracy': 0.931159542810767}\n",
      "epoch: 15 step: 242, loss is 0.3990159332752228\n",
      "epoch: 15 step: 1242, loss is 0.2789316475391388\n",
      "epoch: 15 step: 2242, loss is 0.23281070590019226\n",
      "epoch: 15 step: 3242, loss is 0.3102906048297882\n",
      "epoch: 16 step: 545, loss is 0.2600497901439667\n",
      "epoch: 16 step: 1545, loss is 0.2706286311149597\n",
      "epoch: 16 step: 2545, loss is 0.37438470125198364\n",
      "epoch: 16 step: 3545, loss is 0.30041372776031494\n",
      "验证集准确率为: {'accuracy': 0.9296040173136751}\n",
      "epoch: 17 step: 848, loss is 0.26352012157440186\n",
      "epoch: 17 step: 1848, loss is 0.2437521368265152\n",
      "epoch: 17 step: 2848, loss is 0.2724604904651642\n",
      "epoch: 18 step: 151, loss is 0.2848968207836151\n",
      "epoch: 18 step: 1151, loss is 0.3152933120727539\n",
      "epoch: 18 step: 2151, loss is 0.2985284626483917\n",
      "epoch: 18 step: 3151, loss is 0.2768436670303345\n",
      "验证集准确率为: {'accuracy': 0.9309989178953064}\n",
      "epoch: 19 step: 454, loss is 0.31289243698120117\n",
      "epoch: 19 step: 1454, loss is 0.2889769375324249\n",
      "epoch: 19 step: 2454, loss is 0.36934804916381836\n",
      "epoch: 19 step: 3454, loss is 0.27359330654144287\n",
      "epoch: 20 step: 757, loss is 0.3022765517234802\n",
      "epoch: 20 step: 1757, loss is 0.3043055534362793\n",
      "epoch: 20 step: 2757, loss is 0.35668396949768066\n",
      "验证集准确率为: {'accuracy': 0.9310580954957393}\n",
      "---------------训练结束-------------\n"
     ]
    }
   ],
   "source": [
    "from mindspore.train.callback import LossMonitor, TimeMonitor, Callback,CheckpointConfig,ModelCheckpoint\n",
    "\n",
    "# 自定义回调类（继承Callback类），用于计算输出验证集准确率\n",
    "class ValCallBack(Callback):\n",
    "    def __init__(self, model, val_dataset, epochs_to_val, per_val, dataset_sink_mode=False):\n",
    "        self.model = model\n",
    "        self.val_dataset = val_dataset      # 输出验证集准确率的epoch间隔数\n",
    "        self.epochs_to_val = epochs_to_val  # 一个记录当前epoch和val_acc值的字典\n",
    "        self.per_val = per_val\n",
    "        self.dataset_sink_mode = dataset_sink_mode\n",
    "\n",
    "    def epoch_end(self, run_context):\n",
    "        # 获取到现在的epoch数\n",
    "        cb_param = run_context.original_args()\n",
    "        cur_epoch = cb_param.cur_epoch_num\n",
    "        # 如果达到进行验证的epoch数，则进行以下验证操作\n",
    "        if cur_epoch % self.epochs_to_val == 0:\n",
    "            # 此处model设定的metrics是准确率Accuracy\n",
    "            acc = self.model.eval(self.val_dataset, dataset_sink_mode=self.dataset_sink_mode)\n",
    "            self.per_val[\"epoch\"].append(cur_epoch)\n",
    "            self.per_val[\"acc\"].append(acc)\n",
    "            print(\"验证集准确率为: {}\".format(acc))\n",
    "\n",
    "#实例化回调对象\n",
    "epochs_to_val = 2                    # 每隔2个epoch在验证集上进行一次验证\n",
    "val_acc = {'epoch':[], 'acc':[]}     # 记录当前epoch数和acc值\n",
    "valAcc_cb = ValCallBack(model,data_val,epochs_to_val, val_acc)\n",
    "# 回调训练过程中的loss值\n",
    "loss_cb = LossMonitor(per_print_times=1000)\n",
    "\n",
    "epoches = 20\n",
    "print('---------------开始训练-------------')\n",
    "model.train(epoches, data_train, callbacks=[loss_cb,valAcc_cb], dataset_sink_mode=False)\n",
    "print('---------------训练结束-------------')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "cc8aa5db-5db9-4647-8efb-c3545ac25fcb",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The accuracy of the test dataset is {'accuracy': 0.9307058608949417}\n"
     ]
    }
   ],
   "source": [
    "# 使用验证集评估模型，打印总体准确率\n",
    "acc = model.eval(data_test)\n",
    "print('The accuracy of the test dataset is {}'.format(acc))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "f68cb274-dde3-49c2-9dda-cafb4d010e7f",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "ms.save_checkpoint(net, \"DNN.ckpt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a29dd92-1893-4fc5-8242-f835fdeb6cbb",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:MindSpore] *",
   "language": "python",
   "name": "conda-env-MindSpore-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.13"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
